// app/service/reconciliation_service.js
'use strict';

const { Service } = require('egg');

class ReconciliationService extends Service {
  // 智能对账业务逻辑
  async performSmartReconciliation(algorithm = 'comprehensive', options = {}) {
    const { ctx } = this;
    
    // 设置默认选项
    const {
      confidence_threshold = 50,
      time_range_days = 30,
      enable_fuzzy_match = true
    } = options;
    
    // 记录开始时间用于性能统计
    const startTime = Date.now();
    
    try {
      // 获取待匹配的银行流水
      const transactions = await ctx.model.BankTransactionModel.findAll({
        where: { isFiltered: false }
      });
      
      // 获取待匹配的销售订单
      const orders = await ctx.model.SalesOrderModel.findAll({
        where: { 
          orderStatus: 'completed',
          id: {
            [ctx.app.Sequelize.Op.notIn]: ctx.app.Sequelize.literal(
              '(SELECT sales_order_id FROM reconciliation_results WHERE match_status = "confirmed")'
            )
          }
        }
      });
      
      // 调用匹配引擎
      const matches = await ctx.service.reconciliationEngineService.execute(
        transactions,
        orders,
        algorithm,
        {
          confidence_threshold,
          time_range_days,
          enable_fuzzy_match
        }
      );
      
      // 过滤置信度阈值
      const filteredMatches = matches.filter(match => match.matchConfidence >= confidence_threshold);
      
      // 计算统计信息
      const processingTime = Date.now() - startTime;
      const statistics = {
        total_processed: transactions.length + orders.length,
        matched_count: filteredMatches.length,
        high_confidence_count: filteredMatches.filter(m => m.matchConfidence >= 80).length,
        avg_confidence: filteredMatches.length > 0 
          ? Math.round(filteredMatches.reduce((sum, m) => sum + m.matchConfidence, 0) / filteredMatches.length * 100) / 100
          : 0,
        processing_time: `${processingTime}ms`
      };
      
      // 性能检查 - 95%的请求应在200ms内完成
      if (processingTime > 200) {
        ctx.logger.warn(`智能匹配处理时间较长: ${processingTime}ms`);
      }
      
      return {
        matches: filteredMatches,
        statistics
      };
    } catch (error) {
      ctx.logger.error('智能对账业务逻辑执行失败:', error);
      // 抛出业务异常，由控制层统一处理
      throw new Error('智能对账业务逻辑执行失败: ' + error.message);
    }
  }
  
  // 手动匹配业务逻辑
  async performManualMatch(transactionIds, orderIds, algorithm = 'comprehensive', userId = null) {
    const { ctx } = this;
    
    try {
      // 验证提供的ID在数据库中是否存在
      const transactionIdInts = transactionIds.map(id => parseInt(id));
      const orderIdInts = orderIds.map(id => parseInt(id));
      
      // 检查银行流水ID是否存在
      const existingTransactions = await ctx.model.BankTransactionModel.findAll({
        where: {
          id: {
            [ctx.app.Sequelize.Op.in]: transactionIdInts
          }
        }
      });
      
      if (existingTransactions.length !== transactionIdInts.length) {
        throw new Error('部分银行流水ID不存在');
      }
      
      // 检查销售订单ID是否存在
      const existingOrders = await ctx.model.SalesOrderModel.findAll({
        where: {
          id: {
            [ctx.app.Sequelize.Op.in]: orderIdInts
          }
        }
      });
      
      if (existingOrders.length !== orderIdInts.length) {
        throw new Error('部分销售订单ID不存在');
      }
      
      // 使用事务确保数据一致性
      const result = await ctx.model.transaction(async () => {
        const matches = [];
        for (const transId of transactionIds) {
          for (const orderId of orderIds) {
            // 检查是否已经存在相同的匹配记录
            const existingMatch = await ctx.model.ReconciliationResultModel.findOne({
              where: {
                salesOrderId: parseInt(orderId),
                bankTransactionId: parseInt(transId)
              }
            });
            
            if (existingMatch) {
              // 如果已存在，更新状态而不是创建新记录
              await existingMatch.update({
                matchType: 'manual',
                matchConfidence: 100,
                matchStatus: 'confirmed',
                matchedBy: userId,
                matchedAt: new Date(),
                matchAlgorithm: algorithm
              });
              matches.push(existingMatch);
            } else {
              // 创建新的匹配记录
              const match = await ctx.model.ReconciliationResultModel.create({
                salesOrderId: parseInt(orderId),
                bankTransactionId: parseInt(transId),
                matchType: 'manual',
                matchConfidence: 100,
                matchStatus: 'confirmed',
                matchedBy: userId,
                matchedAt: new Date(),
                matchAlgorithm: algorithm
              });
              matches.push(match);
            }
          }
        }
        
        return matches;
      });
      
      return result;
    } catch (error) {
      ctx.logger.error('手动匹配业务逻辑执行失败:', error);
      // 抛出业务异常，由控制层统一处理
      throw new Error('手动匹配业务逻辑执行失败: ' + error.message);
    }
  }
  
  // 获取对账结果业务逻辑
  async getReconciliationResults(queryParams) {
    const { ctx } = this;
    const {
      page = 1,
      limit = 20,
      matchStatus,
      confidenceRange,
      customerName,
      reconciliationDateRange,
      maxAmountDiff,
      algorithm,
      operator,
      dataSource,
      includeDifferences
    } = queryParams;

    try {
      // 构建查询条件
      const whereClause = {};
      
      // 匹配状态筛选
      if (matchStatus && matchStatus !== '') {
        whereClause.matchStatus = matchStatus;
      }
      
      // 算法筛选
      if (algorithm && algorithm !== '') {
        whereClause.matchAlgorithm = algorithm;
      }
      
      // 置信度范围筛选
      if (confidenceRange && Array.isArray(confidenceRange) && confidenceRange.length === 2) {
        const [minConfidence, maxConfidence] = confidenceRange.map(Number);
        whereClause.matchConfidence = {
          [ctx.app.Sequelize.Op.gte]: minConfidence,
          [ctx.app.Sequelize.Op.lte]: maxConfidence
        };
      }
      
      // 日期范围筛选
      if (reconciliationDateRange && Array.isArray(reconciliationDateRange) && reconciliationDateRange.length === 2) {
        const [startDate, endDate] = reconciliationDateRange;
        whereClause.createdAt = {
          [ctx.app.Sequelize.Op.gte]: new Date(startDate),
          [ctx.app.Sequelize.Op.lte]: new Date(endDate)
        };
      }

      // 构建包含关联的查询
      const queryOptions = {
        where: whereClause,
        include: [
          {
            model: ctx.model.SalesOrderModel,
            as: 'salesOrder',
            attributes: ['id', 'platformOrderId', 'orderAmount', 'orderDate', 'customerId'],
            include: [
              {
                model: ctx.model.CustomerModel,
                as: 'customer',
                attributes: ['id', 'name']
              }
            ]
          },
          {
            model: ctx.model.BankTransactionModel,
            as: 'bankTransaction',
            attributes: ['id', 'transactionId', 'payerName', 'amount', 'transactionDate']
          }
        ],
        order: [['matchedAt', 'DESC']],
        limit: parseInt(limit),
        offset: (parseInt(page) - 1) * parseInt(limit)
      };

      // 客户名称筛选
      if (customerName) {
        queryOptions.include[0].where = {
          '$salesOrder.customer.name$': {
            [ctx.app.Sequelize.Op.like]: `%${customerName}%`
          }
        };
      }

      // 执行查询
      const { rows, count } = await ctx.model.ReconciliationResultModel.findAndCountAll(queryOptions);

      // 转换数据格式
      const transformedResults = rows.map(result => {
        const salesOrder = result.salesOrder || {};
        const customer = salesOrder.customer || {};
        const bankTransaction = result.bankTransaction || {};

        return {
          id: result.id,
          salesOrderId: salesOrder.id,
          platformOrderId: salesOrder.platformOrderId,
          orderAmount: salesOrder.orderAmount,
          orderDate: salesOrder.orderDate,
          customerId: customer.id,
          customerName: customer.name || '', // 使用正确的字段名'name'
          bankTransactionId: bankTransaction.id,
          transactionId: bankTransaction.transactionId,
          payerName: bankTransaction.payerName,
          transactionAmount: bankTransaction.amount,
          transactionDate: bankTransaction.transactionDate,
          matchType: result.matchType,
          matchConfidence: result.matchConfidence,
          matchStatus: result.matchStatus,
          algorithmUsed: result.matchAlgorithm, // 修正字段名
          createdAt: result.createdAt,
          updatedAt: result.updatedAt
        };
      });

      return {
        matches: transformedResults,
        pagination: {
          page: parseInt(page),
          limit: parseInt(limit),
          total: count,
          totalPages: Math.ceil(count / parseInt(limit))
        }
      };
    } catch (error) {
      ctx.logger.error('获取对账结果业务逻辑执行失败:', error);
      // 抛出业务异常，由控制层统一处理
      throw new Error('获取对账结果业务逻辑执行失败: ' + error.message);
    }
  }
  
  // 重新运行对账业务逻辑
  async reReconcile(matchIds = null) {
    const { ctx } = this;
    
    try {
      // 使用事务确保数据一致性
      await ctx.model.transaction(async () => {
        // 如果提供了特定的匹配ID，则只重新运行这些匹配
        if (matchIds && Array.isArray(matchIds) && matchIds.length > 0) {
          // 删除现有的匹配记录
          await ctx.model.ReconciliationResultModel.destroy({
            where: {
              id: {
                [ctx.app.Sequelize.Op.in]: matchIds
              }
            }
          });
          
          // TODO: 重新运行对账逻辑
          // 这里应该调用对账引擎重新处理这些匹配
        } else {
          // 如果没有提供特定ID，则重新运行所有对账
          // 删除所有匹配记录
          await ctx.model.ReconciliationResultModel.destroy({
            where: {}
          });
          
          // TODO: 重新运行对账逻辑
          // 这里应该调用对账引擎重新处理所有数据
        }
      });
      
      return { message: '重新对账任务已启动' };
    } catch (error) {
      ctx.logger.error('重新运行对账业务逻辑执行失败:', error);
      // 抛出业务异常，由控制层统一处理
      throw new Error('重新运行对账业务逻辑执行失败: ' + error.message);
    }
  }
  
  // 数据处理和转换
  async processReconciliationData(rawData) {
    // 数据处理逻辑
    // 这里可以添加数据清洗、格式化、验证等逻辑
    return rawData;
  }
}

module.exports = ReconciliationService;